import { describe, expect, test } from "bun:test";
import fs from "fs";
import { bunEnv, bunExe, tempDirWithFiles } from "harness";
import { join } from "path";

describe("yarn.lock migration basic", () => {
  test("simple yarn.lock migration produces correct bun.lock", async () => {
    const tempDir = tempDirWithFiles("yarn-migration-simple", {
      "package.json": JSON.stringify(
        {
          name: "simple-test",
          version: "1.0.0",
          dependencies: {
            "is-number": "^7.0.0",
          },
        },
        null,
        2,
      ),
      "yarn.lock": `# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1


is-number@^7.0.0:
  version "7.0.0"
  resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
  integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
`,
    });

    // Run bun pm migrate
    const migrateResult = await Bun.spawn({
      cmd: [bunExe(), "pm", "migrate", "-f"],
      cwd: tempDir,
      env: bunEnv,
      stdout: "pipe",
      stderr: "pipe",
      stdin: "ignore",
    });

    const [stdout, stderr, exitCode] = await Promise.all([
      new Response(migrateResult.stdout).text(),
      new Response(migrateResult.stderr).text(),
      migrateResult.exited,
    ]);

    expect(exitCode).toBe(0);
    expect(fs.existsSync(join(tempDir, "bun.lock"))).toBe(true);

    const bunLockContent = fs.readFileSync(join(tempDir, "bun.lock"), "utf8");
    expect(bunLockContent).toMatchSnapshot("simple-yarn-migration");
  });

  test("yarn.lock with packages containing long build tags", async () => {
    const tempDir = tempDirWithFiles("yarn-migration-build-tags", {
      "package.json": JSON.stringify(
        {
          name: "build-tags-test",
          version: "1.0.0",
          dependencies: {
            "@prisma/engines-version": "4.16.1-1.4bc8b6e1b66cb932731fb1bdbbc550d1e010de81",
            "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2",
            "@babel/preset-modules": "0.1.6-no-external-plugins",
          },
        },
        null,
        2,
      ),
      "yarn.lock": `# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1


"@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2":
  version "7.21.0-placeholder-for-preset-env.2"
  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz#7844f9289546efa9febac2de4cfe358a050bd703"
  integrity sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==

"@babel/preset-modules@0.1.6-no-external-plugins":
  version "0.1.6-no-external-plugins"
  resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz#ccb88a2c49c817236861fee7826080573b8a923a"
  integrity sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==
  dependencies:
    "@babel/helper-plugin-utils" "^7.0.0"
    "@babel/types" "^7.4.4"
    esutils "^2.0.2"

"@babel/helper-plugin-utils@^7.0.0":
  version "7.22.5"
  resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz#dd7ee3735e8a313b9f7b05a773d892e88e6d7295"
  integrity sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==

"@babel/types@^7.4.4":
  version "7.23.0"
  resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.23.0.tgz#61c5b592274a82bb7addc5073ee1d989799e75e4"
  integrity sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==
  dependencies:
    "@babel/helper-string-parser" "^7.22.5"
    "@babel/helper-validator-identifier" "^7.22.20"
    to-fast-properties "^2.0.0"

"@babel/helper-string-parser@^7.22.5":
  version "7.22.5"
  resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz#533f36457a25814cf1df6488523ad547d784a99f"
  integrity sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==

"@babel/helper-validator-identifier@^7.22.20":
  version "7.22.20"
  resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0"
  integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==

"@prisma/engines-version@4.16.1-1.4bc8b6e1b66cb932731fb1bdbbc550d1e010de81":
  version "4.16.1-1.4bc8b6e1b66cb932731fb1bdbbc550d1e010de81"
  resolved "https://registry.yarnpkg.com/@prisma/engines-version/-/engines-version-4.16.1-1.4bc8b6e1b66cb932731fb1bdbbc550d1e010de81.tgz#5512069ca14c44af7f38e7c39d9a169480e63a33"
  integrity sha512-q617EUWfRIDTriWADZ4YiWRZXCa/WuhNgLTVd+HqWLffjMSPzyM5uOWoauX91wvQClSKZU4pzI4JJLQ9Kl62Qg==

esutils@^2.0.2:
  version "2.0.3"
  resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64"
  integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==

to-fast-properties@^2.0.0:
  version "2.0.0"
  resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e"
  integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==
`,
    });

    // Run bun pm migrate
    const migrateResult = await Bun.spawn({
      cmd: [bunExe(), "pm", "migrate", "-f"],
      cwd: tempDir,
      env: bunEnv,
      stdout: "pipe",
      stderr: "pipe",
      stdin: "ignore",
    });

    const [stdout, stderr, exitCode] = await Promise.all([
      new Response(migrateResult.stdout).text(),
      new Response(migrateResult.stderr).text(),
      migrateResult.exited,
    ]);

    expect(exitCode).toBe(0);
    expect(fs.existsSync(join(tempDir, "bun.lock"))).toBe(true);

    const bunLockContent = fs.readFileSync(join(tempDir, "bun.lock"), "utf8");

    // Verify that long build tags are preserved correctly
    expect(bunLockContent).toContain("4.16.1-1.4bc8b6e1b66cb932731fb1bdbbc550d1e010de81");
    expect(bunLockContent).toContain("7.21.0-placeholder-for-preset-env.2");
    expect(bunLockContent).toContain("0.1.6-no-external-plugins");

    // Ensure no corrupted version strings
    expect(bunLockContent).not.toContain("monoreporeact");
    expect(bunLockContent).not.toContain("@types/react");
    expect(bunLockContent).not.toContain("�");

    // Install should work after migration
    const installResult = await Bun.spawn({
      cmd: [bunExe(), "install"],
      cwd: tempDir,
      env: bunEnv,
      stdout: "pipe",
      stderr: "pipe",
      stdin: "ignore",
    });

    const installExitCode = await installResult.exited;
    expect(installExitCode).toBe(0);
  });

  test("yarn.lock with extremely long build tags (regression test)", async () => {
    const tempDir = tempDirWithFiles("yarn-migration-extreme-build-tags", {
      "package.json": JSON.stringify(
        {
          name: "extreme-build-tags-test",
          version: "1.0.0",
          dependencies: {
            "test-package":
              "1.0.0-alpha.beta.gamma.delta.epsilon.zeta.eta.theta.iota.kappa.lambda.mu.nu.xi.omicron.pi.rho.sigma.tau.upsilon.phi.chi.psi.omega.0123456789abcdef",
          },
        },
        null,
        2,
      ),
      "yarn.lock": `# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1


test-package@1.0.0-alpha.beta.gamma.delta.epsilon.zeta.eta.theta.iota.kappa.lambda.mu.nu.xi.omicron.pi.rho.sigma.tau.upsilon.phi.chi.psi.omega.0123456789abcdef:
  version "1.0.0-alpha.beta.gamma.delta.epsilon.zeta.eta.theta.iota.kappa.lambda.mu.nu.xi.omicron.pi.rho.sigma.tau.upsilon.phi.chi.psi.omega.0123456789abcdef"
  resolved "https://registry.yarnpkg.com/test-package/-/test-package-1.0.0-alpha.beta.gamma.delta.epsilon.zeta.eta.theta.iota.kappa.lambda.mu.nu.xi.omicron.pi.rho.sigma.tau.upsilon.phi.chi.psi.omega.0123456789abcdef.tgz#abc123"
  integrity sha512-xjEohWws8kKwCqz1IbvMrLynEfS7pFdO0CwjbPvzkt+rpL6tpnAKHS0N8d6diEBSp2BAIkUENc6H6H9SEqf0uA==
`,
    });

    // Run bun pm migrate
    const migrateResult = await Bun.spawn({
      cmd: [bunExe(), "pm", "migrate", "-f"],
      cwd: tempDir,
      env: bunEnv,
      stdout: "pipe",
      stderr: "pipe",
      stdin: "ignore",
    });

    const exitCode = await migrateResult.exited;
    expect(exitCode).toBe(0);

    const bunLockPath = join(tempDir, "bun.lock");
    expect(fs.existsSync(bunLockPath)).toBe(true);

    const bunLockContent = fs.readFileSync(bunLockPath, "utf8");

    // The entire long version string should be preserved
    const expectedVersion =
      "1.0.0-alpha.beta.gamma.delta.epsilon.zeta.eta.theta.iota.kappa.lambda.mu.nu.xi.omicron.pi.rho.sigma.tau.upsilon.phi.chi.psi.omega.0123456789abcdef";
    expect(bunLockContent).toContain(expectedVersion);

    // Should not contain any corruption artifacts
    expect(bunLockContent).not.toContain("�");
    expect(bunLockContent).not.toContain("\0");
    expect(bunLockContent).not.toContain("undefined");
    expect(bunLockContent).not.toContain("null");
  });

  test("complex yarn.lock with multiple dependencies and versions", async () => {
    const tempDir = tempDirWithFiles("yarn-migration-complex", {
      "package.json": JSON.stringify(
        {
          name: "complex-test",
          version: "1.0.0",
          dependencies: {
            "express": "^4.18.2",
            "lodash": "^4.17.21",
          },
          devDependencies: {
            "jest": "^29.0.0",
            "typescript": "^5.0.0",
          },
          optionalDependencies: {
            "fsevents": "^2.3.2",
          },
          peerDependencies: {
            "react": "^18.0.0",
          },
        },
        null,
        2,
      ),
      "yarn.lock": `# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1


accepts@~1.3.8:
  version "1.3.8"
  resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e"
  integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==
  dependencies:
    mime-types "~2.1.34"
    negotiator "0.6.3"

array-flatten@1.1.1:
  version "1.1.1"
  resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2"
  integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==

body-parser@1.20.1:
  version "1.20.1"
  resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.1.tgz#b1812a8912c195cd371a3ee5e66faa2338a5c668"
  integrity sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==
  dependencies:
    bytes "3.1.2"
    content-type "~1.0.4"
    debug "2.6.9"
    depd "2.0.0"
    destroy "1.2.0"
    http-errors "2.0.0"
    iconv-lite "0.4.24"
    on-finished "2.4.1"
    qs "6.11.0"
    raw-body "2.5.1"
    type-is "~1.6.18"
    unpipe "1.0.0"

bytes@3.1.2:
  version "3.1.2"
  resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5"
  integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==

content-disposition@0.5.4:
  version "0.5.4"
  resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe"
  integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==
  dependencies:
    safe-buffer "5.2.1"

content-type@~1.0.4:
  version "1.0.5"
  resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918"
  integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==

cookie-signature@1.0.6:
  version "1.0.6"
  resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c"
  integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==

cookie@0.5.0:
  version "0.5.0"
  resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b"
  integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==

debug@2.6.9:
  version "2.6.9"
  resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
  integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==
  dependencies:
    ms "2.0.0"

depd@2.0.0:
  version "2.0.0"
  resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df"
  integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==

destroy@1.2.0:
  version "1.2.0"
  resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015"
  integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==

ee-first@1.1.1:
  version "1.1.1"
  resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
  integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==

encodeurl@~1.0.2:
  version "1.0.2"
  resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
  integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==

escape-html@~1.0.3:
  version "1.0.3"
  resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
  integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==

etag@~1.8.1:
  version "1.8.1"
  resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
  integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==

express@^4.18.2:
  version "4.18.2"
  resolved "https://registry.yarnpkg.com/express/-/express-4.18.2.tgz#3fabe08296e930c796c19e3c516979386ba9fd59"
  integrity sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==
  dependencies:
    accepts "~1.3.8"
    array-flatten "1.1.1"
    body-parser "1.20.1"
    content-disposition "0.5.4"
    content-type "~1.0.4"
    cookie "0.5.0"
    cookie-signature "1.0.6"
    debug "2.6.9"
    depd "2.0.0"
    encodeurl "~1.0.2"
    escape-html "~1.0.3"
    etag "~1.8.1"
    finalhandler "1.2.0"
    fresh "0.5.2"
    http-errors "2.0.0"
    merge-descriptors "1.0.1"
    methods "~1.1.2"
    on-finished "2.4.1"
    parseurl "~1.3.3"
    path-to-regexp "0.1.7"
    proxy-addr "~2.0.7"
    qs "6.11.0"
    range-parser "~1.2.1"
    safe-buffer "5.2.1"
    send "0.18.0"
    serve-static "1.15.0"
    setprototypeof "1.2.0"
    statuses "2.0.1"
    type-is "~1.6.18"
    utils-merge "1.0.1"
    vary "~1.1.2"

finalhandler@1.2.0:
  version "1.2.0"
  resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.2.0.tgz#7d23fe5731b207b4640e4fcd00aec1f9207a7b32"
  integrity sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==
  dependencies:
    debug "2.6.9"
    encodeurl "~1.0.2"
    escape-html "~1.0.3"
    on-finished "2.4.1"
    parseurl "~1.3.3"
    statuses "2.0.1"
    unpipe "~1.0.0"

forwarded@0.2.0:
  version "0.2.0"
  resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811"
  integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==

fresh@0.5.2:
  version "0.5.2"
  resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7"
  integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==

fsevents@^2.3.2:
  version "2.3.3"
  resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6"
  integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==

function-bind@^1.1.1:
  version "1.1.2"
  resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c"
  integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==

get-intrinsic@^1.0.2:
  version "1.2.2"
  resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.2.tgz#281b7622971123e1ef4b3c90fd7539306da93f3b"
  integrity sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==
  dependencies:
    function-bind "^1.1.2"
    has-proto "^1.0.1"
    has-symbols "^1.0.3"
    hasown "^2.0.0"

gopd@^1.0.1:
  version "1.0.1"
  resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c"
  integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==
  dependencies:
    get-intrinsic "^1.1.3"

has-property-descriptors@^1.0.0:
  version "1.0.1"
  resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz#52ba30b6c5ec87fd89fa574bc1c39125c6f65340"
  integrity sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==
  dependencies:
    get-intrinsic "^1.2.2"

has-proto@^1.0.1:
  version "1.0.1"
  resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.1.tgz#1885c1305538958aff469fef37937c22795408e0"
  integrity sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==

has-symbols@^1.0.3:
  version "1.0.3"
  resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8"
  integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==

hasown@^2.0.0:
  version "2.0.0"
  resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.0.tgz#f4c513d454a57b7c7e1650778de226b11700546c"
  integrity sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==
  dependencies:
    function-bind "^1.1.2"

http-errors@2.0.0:
  version "2.0.0"
  resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3"
  integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==
  dependencies:
    depd "2.0.0"
    inherits "2.0.4"
    setprototypeof "1.2.0"
    statuses "2.0.1"
    toidentifier "1.0.1"

iconv-lite@0.4.24:
  version "0.4.24"
  resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
  integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
  dependencies:
    safer-buffer ">= 2.1.2 < 3"

inherits@2.0.4:
  version "2.0.4"
  resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
  integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzBkH31s2EbTbs6iVFEJElQzL5aORl2ATXXJaOmXa2w=

ipaddr.js@1.9.1:
  version "1.9.1"
  resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3"
  integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==

jest@^29.0.0:
  version "29.7.0"
  resolved "https://registry.yarnpkg.com/jest/-/jest-29.7.0.tgz#994676fc24177f088f1c5e3737f5697204ff2613"
  integrity sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==
  dependencies:
    "@jest/core" "^29.7.0"
    "@jest/types" "^29.6.3"
    import-local "^3.0.2"
    jest-cli "^29.7.0"

lodash@^4.17.21:
  version "4.17.21"
  resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
  integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==

media-typer@0.3.0:
  version "0.3.0"
  resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
  integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==

merge-descriptors@1.0.1:
  version "1.0.1"
  resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61"
  integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==

methods@~1.1.2:
  version "1.1.2"
  resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
  integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==

mime-db@1.52.0:
  version "1.52.0"
  resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70"
  integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==

mime-types@~2.1.24, mime-types@~2.1.34:
  version "2.1.35"
  resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a"
  integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==
  dependencies:
    mime-db "1.52.0"

mime@1.6.0:
  version "1.6.0"
  resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1"
  integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==

ms@2.0.0:
  version "2.0.0"
  resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
  integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==

ms@2.1.3:
  version "2.1.3"
  resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
  integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==

negotiator@0.6.3:
  version "0.6.3"
  resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd"
  integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==

object-inspect@^1.13.1:
  version "1.13.1"
  resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.1.tgz#b96c6109324ccfef6b12216a956ca4dc2ff94bc2"
  integrity sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==

on-finished@2.4.1:
  version "2.4.1"
  resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f"
  integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==
  dependencies:
    ee-first "1.1.1"

parseurl@~1.3.3:
  version "1.3.3"
  resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4"
  integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==

path-to-regexp@0.1.7:
  version "0.1.7"
  resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
  integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==

proxy-addr@~2.0.7:
  version "2.0.7"
  resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025"
  integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==
  dependencies:
    forwarded "0.2.0"
    ipaddr.js "1.9.1"

qs@6.11.0:
  version "6.11.0"
  resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a"
  integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==
  dependencies:
    side-channel "^1.0.4"

range-parser@~1.2.1:
  version "1.2.1"
  resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031"
  integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==

raw-body@2.5.1:
  version "2.5.1"
  resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.1.tgz#fe1b1628b181b700215e5fd42389f98b71392857"
  integrity sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==
  dependencies:
    bytes "3.1.2"
    http-errors "2.0.0"
    iconv-lite "0.4.24"
    unpipe "1.0.0"

react@^18.0.0:
  version "18.2.0"
  resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5"
  integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==
  dependencies:
    loose-envify "^1.1.0"

safe-buffer@5.2.1:
  version "5.2.1"
  resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
  integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==

"safer-buffer@>= 2.1.2 < 3":
  version "2.1.2"
  resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
  integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==

send@0.18.0:
  version "0.18.0"
  resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be"
  integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==
  dependencies:
    debug "2.6.9"
    depd "2.0.0"
    destroy "1.2.0"
    encodeurl "~1.0.2"
    escape-html "~1.0.3"
    etag "~1.8.1"
    fresh "0.5.2"
    http-errors "2.0.0"
    mime "1.6.0"
    ms "2.1.3"
    on-finished "2.4.1"
    range-parser "~1.2.1"
    statuses "2.0.1"

serve-static@1.15.0:
  version "1.15.0"
  resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540"
  integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==
  dependencies:
    encodeurl "~1.0.2"
    escape-html "~1.0.3"
    parseurl "~1.3.3"
    send "0.18.0"

set-function-length@^1.1.1:
  version "1.1.1"
  resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.1.1.tgz#4bc39fafb0307224a33e106a7d35ca1218d659ed"
  integrity sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==
  dependencies:
    define-data-property "^1.1.1"
    get-intrinsic "^1.2.1"
    gopd "^1.0.1"
    has-property-descriptors "^1.0.0"

setprototypeof@1.2.0:
  version "1.2.0"
  resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424"
  integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==

side-channel@^1.0.4:
  version "1.0.4"
  resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf"
  integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==
  dependencies:
    call-bind "^1.0.0"
    get-intrinsic "^1.0.2"
    object-inspect "^1.9.0"

statuses@2.0.1:
  version "2.0.1"
  resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63"
  integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==

toidentifier@1.0.1:
  version "1.0.1"
  resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35"
  integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==

type-is@~1.6.18:
  version "1.6.18"
  resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131"
  integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==
  dependencies:
    media-typer "0.3.0"
    mime-types "~2.1.24"

typescript@^5.0.0:
  version "5.3.3"
  resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.3.3.tgz#b3ce6ba258e72e6305ba66f5c9b452aaee3ffe37"
  integrity sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==

unpipe@1.0.0, unpipe@~1.0.0:
  version "1.0.0"
  resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
  integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==

utils-merge@1.0.1:
  version "1.0.1"
  resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"
  integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==

vary@~1.1.2:
  version "1.1.2"
  resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
  integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==
`,
    });

    // Run bun pm migrate
    const migrateResult = await Bun.spawn({
      cmd: [bunExe(), "pm", "migrate", "-f"],
      cwd: tempDir,
      env: bunEnv,
      stdout: "pipe",
      stderr: "pipe",
      stdin: "ignore",
    });

    const [stdout, stderr, exitCode] = await Promise.all([
      new Response(migrateResult.stdout).text(),
      new Response(migrateResult.stderr).text(),
      migrateResult.exited,
    ]);

    expect(exitCode).toBe(0);
    expect(fs.existsSync(join(tempDir, "bun.lock"))).toBe(true);

    const bunLockContent = fs.readFileSync(join(tempDir, "bun.lock"), "utf8");
    expect(bunLockContent).toMatchSnapshot("complex-yarn-migration");
  });

  test("yarn.lock with npm aliases", async () => {
    const tempDir = tempDirWithFiles("yarn-migration-aliases", {
      "package.json": JSON.stringify(
        {
          name: "alias-test",
          version: "1.0.0",
          dependencies: {
            "@types/bun": "npm:bun-types@1.2.19",
            "my-lodash": "npm:lodash@4.17.21",
          },
        },
        null,
        2,
      ),
      "yarn.lock": `# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1


"@types/bun@npm:bun-types@1.2.19":
  version "1.2.19"
  resolved "https://registry.yarnpkg.com/bun-types/-/bun-types-1.2.19.tgz#0cecd78ed08bae389cc902ae3a5617c390b0fab6"
  integrity sha512-uAOTaZSPuYsWIXRpj7o56Let0g/wjihKCkeRqUBhlLVM/Bt+Fj9xTo+LhC1OV1XDaGkz4hNC80et5xgy+9KTHQ==
  dependencies:
    "@types/node" "*"

"@types/node@*":
  version "20.11.5"
  resolved "https://registry.yarnpkg.com/@types/node/-/node-20.11.5.tgz#be10c622ca7fcaa3cf226cf80166abc31389d86e"
  integrity sha512-g557vgQjUUfN76MZAN/dt1z3dzcUsimuysco0KeluHgrPdJXkP/XdAURgyO2W9fZWHRtRBiVKzKn8vyOAwlG+w==
  dependencies:
    undici-types "~5.26.4"

lodash@4.17.21:
  version "4.17.21"
  resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
  integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==

my-lodash@npm:lodash@4.17.21:
  version "4.17.21"
  resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
  integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==

undici-types@~5.26.4:
  version "5.26.5"
  resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617"
  integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==
`,
    });

    // Run bun pm migrate
    const migrateResult = await Bun.spawn({
      cmd: [bunExe(), "pm", "migrate", "-f"],
      cwd: tempDir,
      env: bunEnv,
      stdout: "pipe",
      stderr: "pipe",
      stdin: "ignore",
    });

    const [stdout, stderr, exitCode] = await Promise.all([
      new Response(migrateResult.stdout).text(),
      new Response(migrateResult.stderr).text(),
      migrateResult.exited,
    ]);

    expect(exitCode).toBe(0);
    expect(fs.existsSync(join(tempDir, "bun.lock"))).toBe(true);

    const bunLockContent = fs.readFileSync(join(tempDir, "bun.lock"), "utf8");
    expect(bunLockContent).toMatchSnapshot("aliases-yarn-migration");

    // Verify that npm aliases are handled correctly
    expect(bunLockContent).toContain('"@types/bun": ["bun-types@1.2.19"');
    expect(bunLockContent).toContain('"my-lodash": ["lodash@4.17.21"');
  });

  test("yarn.lock with resolutions", async () => {
    const tempDir = tempDirWithFiles("yarn-migration-resolutions", {
      "package.json": JSON.stringify(
        {
          name: "resolutions-test",
          version: "1.0.0",
          dependencies: {
            "webpack": "^5.89.0",
          },
          resolutions: {
            "acorn": "8.11.3",
            "webpack/acorn": "8.11.2",
          },
        },
        null,
        2,
      ),
      "yarn.lock": `# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1


acorn@8.11.2:
  version "8.11.2"
  resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.2.tgz#ca0d78b51895be5390a5903c5b3bdcdaf78ae40b"
  integrity sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==

acorn@8.11.3, acorn@^8.7.1, acorn@^8.8.2:
  version "8.11.3"
  resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.3.tgz#71e0b14e13a4ec160724b38fb7b0f233b1b81d7a"
  integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==

webpack@^5.89.0:
  version "5.89.0"
  resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.89.0.tgz#56b8bf9a34356e93a6625770006490bf3a7f32dc"
  integrity sha512-qyfIC10pOr70V+jkmud8tMfajraGCZMBWJtrmuBymQKCrLTRejBI8STDp1MCyZu/QTdZSeacCQYpYNQVOzX5kw==
  dependencies:
    "@types/eslint-scope" "^3.7.3"
    "@types/estree" "^1.0.0"
    "@webassemblyjs/ast" "^1.11.5"
    "@webassemblyjs/wasm-edit" "^1.11.5"
    "@webassemblyjs/wasm-parser" "^1.11.5"
    acorn "^8.7.1"
    acorn-import-assertions "^1.9.0"
    browserslist "^4.14.5"
    chrome-trace-event "^1.0.2"
    enhanced-resolve "^5.15.0"
    es-module-lexer "^1.2.1"
    eslint-scope "5.1.1"
    events "^3.2.0"
    glob-to-regexp "^0.4.1"
    graceful-fs "^4.2.9"
    json-parse-even-better-errors "^2.3.1"
    loader-runner "^4.2.0"
    mime-types "^2.1.27"
    neo-async "^2.6.2"
    schema-utils "^3.2.0"
    tapable "^2.1.1"
    terser-webpack-plugin "^5.3.7"
    watchpack "^2.4.0"
    webpack-sources "^3.2.3"
`,
    });

    // Run bun pm migrate
    const migrateResult = await Bun.spawn({
      cmd: [bunExe(), "pm", "migrate", "-f"],
      cwd: tempDir,
      env: bunEnv,
      stdout: "pipe",
      stderr: "pipe",
      stdin: "ignore",
    });

    const [stdout, stderr, exitCode] = await Promise.all([
      new Response(migrateResult.stdout).text(),
      new Response(migrateResult.stderr).text(),
      migrateResult.exited,
    ]);

    expect(exitCode).toBe(0);
    expect(fs.existsSync(join(tempDir, "bun.lock"))).toBe(true);

    const bunLockContent = fs.readFileSync(join(tempDir, "bun.lock"), "utf8");
    expect(bunLockContent).toMatchSnapshot("resolutions-yarn-migration");

    // Verify resolutions are handled
    expect(bunLockContent).toContain("resolutions");
  });

  test("yarn.lock with workspace dependencies", async () => {
    const tempDir = tempDirWithFiles("yarn-migration-workspace", {
      "package.json": JSON.stringify(
        {
          name: "workspace-root",
          version: "1.0.0",
          private: true,
          workspaces: ["packages/*"],
          dependencies: {
            "lodash": "^4.17.21",
          },
        },
        null,
        2,
      ),
      "packages/a/package.json": JSON.stringify(
        {
          name: "@workspace/a",
          version: "1.0.0",
          dependencies: {
            "@workspace/b": "workspace:*",
            "is-number": "^7.0.0",
          },
        },
        null,
        2,
      ),
      "packages/b/package.json": JSON.stringify(
        {
          name: "@workspace/b",
          version: "1.0.0",
          dependencies: {
            "is-odd": "^3.0.1",
          },
        },
        null,
        2,
      ),
      "yarn.lock": `# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1


"@workspace/b@workspace:*", "@workspace/b@workspace:packages/b":
  version "0.0.0-use.local"
  resolved "file:packages/b"
  dependencies:
    is-odd "^3.0.1"

is-number@^6.0.0:
  version "6.0.0"
  resolved "https://registry.yarnpkg.com/is-number/-/is-number-6.0.0.tgz#e6d15ad31fc262887d1846d1c6c84c9b3b0b5982"
  integrity sha512-Wu1VHeILBK8KAWJUAiSZQX94GmOE45Rg6/538fKwiloUu21KncEkYGPqob2oSZ5mUT73vLGrHQjKw3KMPwfDzg==

is-number@^7.0.0:
  version "7.0.0"
  resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
  integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==

is-odd@^3.0.1:
  version "3.0.1"
  resolved "https://registry.yarnpkg.com/is-odd/-/is-odd-3.0.1.tgz#65101baf63c59f7b5c3a429d0a4e3d8ca7914559"
  integrity sha512-CQpnWPrDwmP1+SMHXZhtLtJv90yiyVfluGsX5iNCVkrhQtU3TQHsUWPG9wkdk9Lgd5yNpAg9jQEo90CBaXgWMA==
  dependencies:
    is-number "^6.0.0"

lodash@^4.17.21:
  version "4.17.21"
  resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
  integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
`,
    });

    // Run bun pm migrate
    const migrateResult = await Bun.spawn({
      cmd: [bunExe(), "pm", "migrate", "-f"],
      cwd: tempDir,
      env: bunEnv,
      stdout: "pipe",
      stderr: "pipe",
      stdin: "ignore",
    });

    const [stdout, stderr, exitCode] = await Promise.all([
      new Response(migrateResult.stdout).text(),
      new Response(migrateResult.stderr).text(),
      migrateResult.exited,
    ]);

    expect(exitCode).toBe(0);
    expect(fs.existsSync(join(tempDir, "bun.lock"))).toBe(true);

    const bunLockContent = fs.readFileSync(join(tempDir, "bun.lock"), "utf8");
    expect(bunLockContent).toMatchSnapshot("workspace-yarn-migration");

    // TODO: Workspace dependencies are not yet supported in yarn migration
    // expect(bunLockContent).toContain("workspace:");
  });

  test("yarn.lock with scoped packages and parent/child relationships", async () => {
    const tempDir = tempDirWithFiles("yarn-migration-scoped", {
      "package.json": JSON.stringify(
        {
          name: "scoped-test",
          version: "1.0.0",
          dependencies: {
            "@babel/core": "^7.23.7",
            "babel-loader": "^9.1.3",
          },
        },
        null,
        2,
      ),
      "yarn.lock": `# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1


"@babel/code-frame@^7.22.13", "@babel/code-frame@^7.23.5":
  version "7.23.5"
  resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.23.5.tgz#9009b69a8c602293476ad598ff53e4562e15c244"
  integrity sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==
  dependencies:
    "@babel/highlight" "^7.23.4"
    chalk "^2.4.2"

"@babel/compat-data@^7.23.5":
  version "7.23.5"
  resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.23.5.tgz#ffb878728bb6bdcb6f4510aa51b1be9afb8cfd98"
  integrity sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==

"@babel/core@^7.23.7":
  version "7.23.7"
  resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.23.7.tgz#4d8016e06a14b5f92530a13ed0561730b5c6483f"
  integrity sha512-+UpDgowcmqe36d4NwqvKsyPMlOLNGMsfMmQ5WGCu+siCe3t3dfe9njrzGfdN4qq+bcNUt0+Vw6haRxBOycs4dw==
  dependencies:
    "@ampproject/remapping" "^2.2.0"
    "@babel/code-frame" "^7.23.5"
    "@babel/generator" "^7.23.6"
    "@babel/helper-compilation-targets" "^7.23.6"
    "@babel/helper-module-transforms" "^7.23.3"
    "@babel/helpers" "^7.23.7"
    "@babel/parser" "^7.23.6"
    "@babel/template" "^7.22.15"
    "@babel/traverse" "^7.23.7"
    "@babel/types" "^7.23.6"
    convert-source-map "^2.0.0"
    debug "^4.1.0"
    gensync "^1.0.0-beta.2"
    json5 "^2.2.3"
    semver "^6.3.1"

"@babel/highlight@^7.23.4":
  version "7.23.4"
  resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.23.4.tgz#edaadf4d8232e1a961432db785091207ead0621b"
  integrity sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==
  dependencies:
    "@babel/helper-validator-identifier" "^7.22.20"
    chalk "^2.4.2"
    js-tokens "^4.0.0"

babel-loader@^9.1.3:
  version "9.1.3"
  resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-9.1.3.tgz#3d0e01b4e69760cc694ee306fe16d358aa1c6f9a"
  integrity sha512-xG3ST4DglodGf8qSwv0MdeWLhrDsw/32QMdTO5T1ZIp9gQur0HkCyFs7Awskr10JKXFXwpAhiCuYX5oGXnRGbw==
  dependencies:
    find-cache-dir "^4.0.0"
    schema-utils "^4.0.0"

chalk@^2.4.2:
  version "2.4.2"
  resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
  integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
  dependencies:
    ansi-styles "^3.2.1"
    escape-string-regexp "^1.0.5"
    supports-color "^5.3.0"

babel-loader/chalk@^2.4.2:
  version "2.4.1"
  resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.1.tgz#18c49ab16a037b6eb0152cc83e3471338215b66e"
  integrity sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==
  dependencies:
    ansi-styles "^3.2.1"
    escape-string-regexp "^1.0.5"
    supports-color "^5.3.0"
`,
    });

    // Run bun pm migrate
    const migrateResult = await Bun.spawn({
      cmd: [bunExe(), "pm", "migrate", "-f"],
      cwd: tempDir,
      env: bunEnv,
      stdout: "pipe",
      stderr: "pipe",
      stdin: "ignore",
    });

    const [stdout, stderr, exitCode] = await Promise.all([
      new Response(migrateResult.stdout).text(),
      new Response(migrateResult.stderr).text(),
      migrateResult.exited,
    ]);

    expect(exitCode).toBe(0);
    expect(fs.existsSync(join(tempDir, "bun.lock"))).toBe(true);

    const bunLockContent = fs.readFileSync(join(tempDir, "bun.lock"), "utf8");
    expect(bunLockContent).toMatchSnapshot("scoped-yarn-migration");

    // Verify scoped packages are at the bottom
    const lines = bunLockContent.split("\n");
    const packageSectionStart = lines.findIndex(line => line.trim().startsWith("packages:"));
    const lastBabelIndex = lines.findLastIndex(line => line.includes("@babel/"));
    const firstNonScopedAfterPackages = lines.findIndex(
      (line, idx) => idx > packageSectionStart && line.includes('"') && !line.includes("/") && !line.includes("@"),
    );

    // Scoped packages should appear after non-scoped ones
    if (firstNonScopedAfterPackages !== -1) {
      expect(lastBabelIndex).toBeGreaterThan(firstNonScopedAfterPackages);
    }
  });

  test("migration with realistic complex yarn.lock", async () => {
    // Create a realistic yarn.lock with various edge cases
    const tempDir = tempDirWithFiles("yarn-migration-complex-realistic", {
      "package.json": JSON.stringify(
        {
          name: "complex-app",
          version: "1.0.0",
          dependencies: {
            "react": "^18.2.0",
            "react-dom": "^18.2.0",
            "@babel/core": "^7.20.0",
            "webpack": "^5.75.0",
          },
          devDependencies: {
            "@types/react": "^18.0.0",
            "typescript": "^4.9.0",
            "eslint": "^8.0.0",
          },
          peerDependencies: {
            "react": ">=16.8.0",
          },
          optionalDependencies: {
            "fsevents": "^2.3.2",
          },
        },
        null,
        2,
      ),
      "yarn.lock": `# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1


"@babel/core@^7.20.0":
  version "7.20.12"
  resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.20.12.tgz#7f12f7fe01cfcc5c4f37fa6e09a6e7ac0736b5e9"
  integrity sha512-XsMfHovsUYHFMdrIHkZphTN/2Hzzi78R08NuHfDBehym2VsPDL6Zn/JAD/JQdnRvbSsbQc4mVaU1m6JgtTEElg==
  dependencies:
    "@ampproject/remapping" "^2.1.0"
    "@babel/code-frame" "^7.18.6"
    "@babel/generator" "^7.20.7"
    "@babel/helper-compilation-targets" "^7.20.7"
    "@babel/helper-module-transforms" "^7.20.11"
    "@babel/helpers" "^7.20.7"
    "@babel/parser" "^7.20.7"
    "@babel/template" "^7.20.7"
    "@babel/traverse" "^7.20.12"
    "@babel/types" "^7.20.7"
    convert-source-map "^1.7.0"
    debug "^4.1.0"
    gensync "^1.0.0-beta.2"
    json5 "^2.2.2"
    semver "^6.3.0"

"@types/react@^18.0.0":
  version "18.0.28"
  resolved "https://registry.yarnpkg.com/@types/react/-/react-18.0.28.tgz#accaeb8b86f4908057ad629a26635fe641480065"
  integrity sha512-RD0ivG1kEztNBdoAK7lekI9M+azSnitIn85h4iOiaLjaTrMjzslhaqCGaI4IyCJ1RljWiLCEu4jyrLLgqxBTew==
  dependencies:
    "@types/prop-types" "*"
    "@types/scheduler" "*"
    csstype "^3.0.2"

eslint@^8.0.0:
  version "8.35.0"
  resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.35.0.tgz#fffad7c7e326bae606f0e8f436a6158566d42323"
  integrity sha512-BxAf1fVL7w+JLRQhWl2pzGeSiGqbWumV4WNvc9Rhp6tiCtm4oHnyPBSEtMGZwrQgudFQ+otqzWoPB7x+hxoWsw==
  dependencies:
    "@eslint/eslintrc" "^2.0.0"
    "@eslint/js" "8.35.0"
    "@humanwhocodes/config-array" "^0.11.8"
    "@humanwhocodes/module-importer" "^1.0.1"
    "@nodelib/fs.walk" "^1.2.8"
    ajv "^6.10.0"
    chalk "^4.0.0"
    cross-spawn "^7.0.2"
    debug "^4.3.2"
    doctrine "^3.0.0"
    escape-string-regexp "^4.0.0"
    eslint-scope "^7.1.1"
    eslint-utils "^3.0.0"
    eslint-visitor-keys "^3.3.0"
    espree "^9.4.0"
    esquery "^1.4.2"
    esutils "^2.0.2"
    fast-deep-equal "^3.1.3"
    file-entry-cache "^6.0.1"
    find-up "^5.0.0"
    glob-parent "^6.0.2"
    globals "^13.19.0"
    grapheme-splitter "^1.0.4"
    ignore "^5.2.0"
    import-fresh "^3.0.0"
    imurmurhash "^0.1.4"
    is-glob "^4.0.0"
    is-path-inside "^3.0.3"
    js-sdsl "^4.1.4"
    js-yaml "^4.1.0"
    json-stable-stringify-without-jsonify "^1.0.1"
    levn "^0.4.1"
    lodash.merge "^4.6.2"
    minimatch "^3.1.2"
    natural-compare "^1.4.0"
    optionator "^0.9.1"
    regexpp "^3.2.0"
    strip-ansi "^6.0.1"
    strip-json-comments "^3.1.0"
    text-table "^0.2.0"

fsevents@^2.3.2:
  version "2.3.2"
  resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
  integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==

"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0:
  version "4.0.0"
  resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
  integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==

loose-envify@^1.1.0:
  version "1.4.0"
  resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
  integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
  dependencies:
    js-tokens "^3.0.0 || ^4.0.0"

react-dom@^18.2.0:
  version "18.2.0"
  resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d"
  integrity sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==
  dependencies:
    loose-envify "^1.1.0"
    scheduler "^0.23.0"

react@^18.2.0:
  version "18.2.0"
  resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5"
  integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==
  dependencies:
    loose-envify "^1.1.0"

scheduler@^0.23.0:
  version "0.23.0"
  resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.0.tgz#ba8041afc3d30eb206a487b6b384002e4e61fdfe"
  integrity sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==
  dependencies:
    loose-envify "^1.1.0"

semver@^6.3.0:
  version "6.3.0"
  resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
  integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==

typescript@^4.9.0:
  version "4.9.5"
  resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.5.tgz#095979f9bcc0d09da324d58d03ce8f8374cbe65a"
  integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==

webpack@^5.75.0:
  version "5.76.0"
  resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.76.0.tgz#f9fb9fb8c4a7dbdcd0d56a98e56b8a942ee2692c"
  integrity sha512-l5sOdYBDunyf72HW8dF23rFtWq/7Zgvt/9ftMof71E/yUb1YLOBmTgA2K4vQthB3kotMrSj609txVE0dnr2fjA==
  dependencies:
    "@types/eslint-scope" "^3.7.3"
    "@types/estree" "^0.0.51"
    "@webassemblyjs/ast" "1.11.1"
    "@webassemblyjs/wasm-edit" "1.11.1"
    "@webassemblyjs/wasm-parser" "1.11.1"
    acorn "^8.7.1"
    acorn-import-assertions "^1.7.6"
    browserslist "^4.14.5"
    chrome-trace-event "^1.0.2"
    enhanced-resolve "^5.10.0"
    es-module-lexer "^0.9.0"
    eslint-scope "5.1.1"
    events "^3.2.0"
    glob-to-regexp "^0.4.1"
    graceful-fs "^4.2.9"
    json-parse-even-better-errors "^2.3.1"
    loader-runner "^4.2.0"
    mime-types "^2.1.27"
    neo-async "^2.6.2"
    schema-utils "^3.1.0"
    tapable "^2.1.1"
    terser-webpack-plugin "^5.1.3"
    watchpack "^2.4.0"
    webpack-sources "^3.2.3"
`,
    });

    // Run bun pm migrate
    const migrateResult = await Bun.spawn({
      cmd: [bunExe(), "pm", "migrate", "-f"],
      cwd: tempDir,
      env: bunEnv,
      stdout: "pipe",
      stderr: "pipe",
      stdin: "ignore",
    });

    const exitCode = await migrateResult.exited;
    expect(exitCode).toBe(0);
    expect(fs.existsSync(join(tempDir, "bun.lock"))).toBe(true);

    const bunLockContent = fs.readFileSync(join(tempDir, "bun.lock"), "utf8");
    expect(bunLockContent).toMatchSnapshot("complex-realistic-yarn-migration");

    // Verify key features are migrated
    expect(bunLockContent).toContain('"react": [');
    expect(bunLockContent).toContain('"@babel/core": [');
    expect(bunLockContent).toContain('"webpack": [');
    expect(bunLockContent).toContain('"typescript": [');

    // Verify peer dependencies are captured
    expect(bunLockContent).toContain("peerDependencies");
  });
});

describe("bun pm migrate for existing yarn.lock", () => {
  const folders = [
    "yarn-cli-repo",
    "yarn-lock-mkdirp",
    "yarn-lock-mkdirp-file-dep",
    "yarn-lock-mkdirp-no-resolved",
    "yarn-stuff",
    "yarn-stuff/abbrev-link-target",
  ];
  test.each(folders)("%s", async folder => {
    const packageJsonContent = await Bun.file(join(import.meta.dir, "yarn", folder, "package.json")).text();
    const yarnLockContent = await Bun.file(join(import.meta.dir, "yarn", folder, "yarn.lock")).text();

    const tempDir = tempDirWithFiles("yarn-lock-migration-", {
      "package.json": packageJsonContent,
      "yarn.lock": yarnLockContent,
    });

    const migrateResult = Bun.spawn({
      cmd: [bunExe(), "pm", "migrate", "-f"],
      cwd: tempDir,
      env: bunEnv,
      stdout: "pipe",
      stderr: "pipe",
      stdin: "ignore",
    });

    expect(migrateResult.exited).resolves.toBe(0);
    expect(Bun.file(join(tempDir, "bun.lock")).exists()).resolves.toBe(true);

    const bunLockContent = await Bun.file(join(tempDir, "bun.lock")).text();
    expect(bunLockContent).toMatchSnapshot(folder);
  });

  test("yarn.lock with packages that have os/cpu requirements", async () => {
    const tempDir = tempDirWithFiles("yarn-migration-os-cpu", {
      "package.json": JSON.stringify(
        {
          name: "os-cpu-test",
          version: "1.0.0",
          dependencies: {
            fsevents: "^2.3.2",
            esbuild: "^0.17.0",
          },
        },
        null,
        2,
      ),
      "yarn.lock": `# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1


"@esbuild/android-arm64@0.17.19":
  version "0.17.19"
  resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.17.19.tgz#bafb75234a5d3d1b690e7c2956a599345e84a2fd"
  integrity sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==

"@esbuild/darwin-arm64@0.17.19":
  version "0.17.19"
  resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.17.19.tgz#584c34c5991b95d4d48d333300b1a4e2ff7be276"
  integrity sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg==

"@esbuild/darwin-x64@0.17.19":
  version "0.17.19"
  resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.17.19.tgz#7751d236dfe6ce136cce343dce69f52d76b7f6cb"
  integrity sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw==

"@esbuild/linux-arm64@0.17.19":
  version "0.17.19"
  resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.17.19.tgz#38e162ecb723862c6be1c27d6389f48960b68edb"
  integrity sha512-ct1Mj/VEUqd5+2h0EBPdMzNdGXnGxbLPg6H5TF8xsHY4X5UAP0FUbDKJhtKu+6iLpIjKjWEvb5XrFyZdVy9OTg==

"@esbuild/linux-x64@0.17.19":
  version "0.17.19"
  resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.17.19.tgz#8a0e9738b1635f0c53389e515ae83826dec22aa4"
  integrity sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw==

esbuild@^0.17.0:
  version "0.17.19"
  resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.17.19.tgz#087a727e98299f0462a3d0bcdd9cd7ff100bd955"
  integrity sha512-XQ0jAPFkK/u3LcVRcvVHQcTIqD6E2H1fvZMA5dQPSOWb3suUbWbfbRf94pjc0bNzRYLfIrDRQXr7X+LHIm5oHw==
  optionalDependencies:
    "@esbuild/android-arm" "0.17.19"
    "@esbuild/android-arm64" "0.17.19"
    "@esbuild/android-x64" "0.17.19"
    "@esbuild/darwin-arm64" "0.17.19"
    "@esbuild/darwin-x64" "0.17.19"
    "@esbuild/freebsd-arm64" "0.17.19"
    "@esbuild/freebsd-x64" "0.17.19"
    "@esbuild/linux-arm" "0.17.19"
    "@esbuild/linux-arm64" "0.17.19"
    "@esbuild/linux-ia32" "0.17.19"
    "@esbuild/linux-loong64" "0.17.19"
    "@esbuild/linux-mips64el" "0.17.19"
    "@esbuild/linux-ppc64" "0.17.19"
    "@esbuild/linux-riscv64" "0.17.19"
    "@esbuild/linux-s390x" "0.17.19"
    "@esbuild/linux-x64" "0.17.19"
    "@esbuild/netbsd-x64" "0.17.19"
    "@esbuild/openbsd-x64" "0.17.19"
    "@esbuild/sunos-x64" "0.17.19"
    "@esbuild/win32-arm64" "0.17.19"
    "@esbuild/win32-ia32" "0.17.19"
    "@esbuild/win32-x64" "0.17.19"

fsevents@^2.3.2:
  version "2.3.2"
  resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
  integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
`,
    });

    // Run bun pm migrate
    const migrateResult = await Bun.spawn({
      cmd: [bunExe(), "pm", "migrate", "-f"],
      cwd: tempDir,
      env: bunEnv,
      stdout: "pipe",
      stderr: "pipe",
      stdin: "ignore",
    });

    const [stdout, stderr, exitCode] = await Promise.all([
      new Response(migrateResult.stdout).text(),
      new Response(migrateResult.stderr).text(),
      migrateResult.exited,
    ]);

    expect(exitCode).toBe(0);
    expect(fs.existsSync(join(tempDir, "bun.lock"))).toBe(true);

    const bunLockContent = fs.readFileSync(join(tempDir, "bun.lock"), "utf8");
    expect(bunLockContent).toMatchSnapshot("os-cpu-yarn-migration");

    // Verify that the lockfile contains the expected os/cpu metadata by checking the snapshot
    // fsevents should have darwin os constraint, esbuild packages should have arch constraints
    expect(bunLockContent).toContain("fsevents");
    expect(bunLockContent).toContain("@esbuild/linux-arm64");
    expect(bunLockContent).toContain("@esbuild/darwin-arm64");
  });
});
